package com.step.math.bak;

import android.util.FloatMath;

import com.step.Step.Dimension;
import com.step.math.Vector;
import com.step.utils.MathUtils;

public class Vector3D extends Vector{
	public float x;
	public float y;
	public float z;
	
	public Vector3D(){
		super(Dimension.d3d);
		this.x = this.y = this.z = 0;
	}
	
	public Vector3D(float x, float y, float z){
		super(Dimension.d3d);
		set(x, y, z);
	}
	
	public Vector3D(Vector3D vector){
		super(Dimension.d3d);
		set(vector);
	}
	
	public Vector3D set(Vector3D vector){
		this.x = vector.x;
		this.y = vector.y;
		this.z = vector.z;
		return this;
	}
	
	public Vector3D set(float x, float y, float z){
		this.x = x;
		this.y = y;
		this.z = z;
		return this;
	}
	
	public Vector3D copy(){
		return new Vector3D(this);
	}
	
	public Vector3D add(Vector3D vector){
		return set(this.x + vector.x, y + vector.y, z + vector.z);
	}
	
	public Vector3D add(float x, float y, float z){
		return set(this.x + x, this.y + y, this.z + z);
	}
	
	public Vector3D sub(float x, float y, float z){
		return set(this.x - x, this.y - y, this.z - z);
	}
	
	public Vector3D sub(Vector3D vector){
		return sub(vector.x, vector.y, vector.z);
	}
	
	public Vector3D mul(float scale){
		return set(this.x * scale, this.y * scale, this.z * scale);
	}
	
	public Vector3D div(float scale){
		if(scale == 0){
			return this;
		}
		
		float d = 1 / scale;
		
		return set(this.x * d, this.y * d, this.z * d);
	}
	
	public float dot(Vector3D vector){
		return this.x * vector.x + this.y * vector.y + this.z * vector.z;
	}
	
	public float dot (float x, float y, float z) {
		return this.x * x + this.y * y + this.z * z;
	}
	
	public Vector3D cro(Vector3D vector){
		return cro(vector.x, vector.y, vector.z);
	}
	
	public Vector3D cro(float x, float y, float z) {
		return this.set(this.y * z - this.z * y, this.z * x - this.x * z, this.x * y - this.y * x);
	}
	
	public float len(){
		return FloatMath.sqrt(lenSQ());
	}
	
	public float lenSQ(){
		return x * x + y * y + z * z;
	}
	
	/**
	 * 判断向量的值是否相等
	 * @param vector
	 * @return
	 */
	public boolean isEquals(Vector3D vector){
		return this.x == vector.x && this.y == vector.y && this.z == vector.z;
	}
	
	public float distSQ(float x, float y, float z){
		float dx = this.x - x;
		float dy = this.y - y; 
		float dz = this.z - z;
		
		return dx * dx + dy * dy + dz * dz;
	}
	
	public float distSQ(Vector3D vector){
		return distSQ(vector.x, vector.y, vector.z);
	}
	
	public float dist(float x, float y, float z){
		return FloatMath.sqrt(distSQ(x, y, z));
	}
	
	public float dist(Vector3D vector){
		return FloatMath.sqrt(distSQ(vector));
	}
	
	public Vector3D nor(){
		float len = len();
		
		if(len == 0){
			return this;
		}
		else{
			return div(len);
		}
	}
	
	public boolean isUnit () {
		return this.len() == 1;
	}
	
	public boolean isZero () {
		return x == 0 && y == 0 && z == 0;
	}
	
	public Vector3D scale (float scalarX, float scalarY, float scalarZ) {
		x *= scalarX;
		y *= scalarY;
		z *= scalarZ;
		return this;
	}
	
private static Vector3D temp = new Vector3D();
	
	public Vector3D rotate(float angle, boolean isRotateX, boolean isRotateY, boolean isRotateZ){
		angle *= MathUtils.degreesToRadians;
		float cosRY = MathUtils.cos(angle);
		float sinRY = MathUtils.sin(angle);
		
		temp.set(this.x, this.y, this.z);
		
		if(isRotateX){
			temp.y = (temp.y * cosRY) - (temp.z * sinRY);
			temp.z = (temp.y * sinRY) + (temp.z * cosRY);
		}
		if(isRotateY){
			temp.x = (temp.x * cosRY) + (temp.z * sinRY);
			temp.z = (temp.x * -sinRY) + (temp.z * cosRY);
		}
		if(isRotateZ){
			temp.x = (temp.x * cosRY) - (temp.y * sinRY);
			temp.y = (temp.x * sinRY) + (temp.y * cosRY);
		}
		return set(temp);
	}
	
	public Vector3D rotate(float angle){
		angle *= MathUtils.degreesToRadians;
		float cosRY = MathUtils.cos(angle);
		float sinRY = MathUtils.sin(angle);

		temp.set(this.x, this.y, this.z);
		// rotate x;
		temp.y = (temp.y * cosRY) - (temp.z * sinRY);
		temp.z = (temp.y * sinRY) + (temp.z * cosRY);
		// rotate y;
		temp.x = (temp.x * cosRY) + (temp.z * sinRY);
		temp.z = (temp.x * -sinRY) + (temp.z * cosRY);
		// rotate z;
		temp.x = (temp.x * cosRY) - (temp.y * sinRY);
		temp.y = (temp.x * sinRY) + (temp.y * cosRY);
		return set(temp);
	}
	
	public Vector3D rotateX(float angle) {
		angle *= MathUtils.degreesToRadians;
		float cosRY = MathUtils.cos(angle);
		float sinRY = MathUtils.sin(angle);

		temp.set(this.x, this.y, this.z);

		this.y = (temp.y * cosRY) - (temp.z * sinRY);
		this.z = (temp.y * sinRY) + (temp.z * cosRY);
		return this;
	}

	public Vector3D rotateY(float angle) {
		angle *= MathUtils.degreesToRadians;		
		float cosRY = MathUtils.cos(angle);
		float sinRY = MathUtils.sin(angle);

		temp.set(this.x, this.y, this.z);

		this.x = (temp.x * cosRY) + (temp.z * sinRY);
		this.z = (temp.x * -sinRY) + (temp.z * cosRY);
		return this;
	}

	public Vector3D rotateZ(float angle) {
		angle *= MathUtils.degreesToRadians;
		float cosRY = MathUtils.cos(angle);
		float sinRY = MathUtils.sin(angle);

		temp.set(this.x, this.y, this.z);

		this.x = (temp.x * cosRY) - (temp.y * sinRY);
		this.y = (temp.x * sinRY) + (temp.y * cosRY);
		return this;
	}
	
	@Override
	public String toString() {
		return "x="+x+",y="+y+",z="+z;
	}

	public static Vector3D add(Vector3D v1, Vector3D v2){
		return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
	}
	
	public static Vector3D sub(Vector3D v1, Vector3D v2){
		return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
	}
	
	public static float dot(Vector3D v1, Vector3D v2){
		return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
	}
	
	public static Vector3D cro(Vector3D v1, Vector3D v2){
		return new Vector3D(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x);
	}
}
